home *** CD-ROM | disk | FTP | other *** search
- Subject: v07i099: Read VMS backup tapes
- Newsgroups: mod.sources
- Approved: mirror!rs
-
- Submitted by: seismo!enea!luthcad!sow (Sven-Ove Westberg)
- Mod.sources: Volume 7, Issue 99
- Archive-name: read-vms-backs
-
- This program reads a VMS backup tape, it can use the rmtlib for remote tape
- access.
- Sven-Ove Westberg
-
- [ I do not have any VMS backup tapes with which to test this. --r$ ]
-
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create:
- # README
- # vmsbackup.1
- # Makefile
- # vmsbackup.c
- # match.c
- # This archive created: Sun Dec 7 19:56:28 1986
- echo shar: "extracting 'README'" '(575 characters)'
- if test -f 'README'
- then
- echo shar: "will not over-write existing file 'README'"
- else
- sed 's/^ X//' << \SHAR_EOF > 'README'
- XThis progam reads a VMS backuptape.
- X
- XThe tape program is orginally written by John Douglas Carey and
- Xthe pattern matching routine by some unknown on the net.
- X
- XThe remote tape option use the rmtlib from mod.sources.
- X
- XA good way to archive remotetape access for users with only
- Xa local account is to create a "netwide" user tar and let
- Xthe remote tape programs do suid to user tar.
- X
- XThe program is tested on vax and sun.
- X
- X
- XSven-Ove Westberg
- XLulea University of Technology
- XS-951 87 Lulea, Sweden
- XUUCP: sow@luthcad.UUCP
- XUUCP: {decvax,philabs,seismo}!mcvax!enea!luthcad!sow
- SHAR_EOF
- if test 575 -ne "`wc -c < 'README'`"
- then
- echo shar: "error transmitting 'README'" '(should have been 575 characters)'
- fi
- fi
- echo shar: "extracting 'vmsbackup.1'" '(3444 characters)'
- if test -f 'vmsbackup.1'
- then
- echo shar: "will not over-write existing file 'vmsbackup.1'"
- else
- sed 's/^ X//' << \SHAR_EOF > 'vmsbackup.1'
- X.TH VMSBACKUP 1
- X.SH NAME
- Xvmsbackup \- read a VMS backup tape
- X.SH SYNOPSIS
- X.B vmsbackup
- X.B \-{tx}[cdevw][s setnumber][f tapefile]
- X[ name ... ]
- X.SH DESCRIPTION
- X.I vmsbackup
- Xreads a VMS generated backup tape, converting the files
- Xto Unix format and writing the files to disc.
- XThe default operation of the program is to go through an entire
- Xtape, extracting every file and writing it to disc.
- XThis may be modified by the following options.
- X.TP 8
- X.B c
- XUse complete filenames, including the version number.
- XA colon and the octal version number will be appended to all filenames.
- XA colon, rather than a semicolon, is used since the Unix Shell
- Xuses the semicolon as the line separator.
- XUsing a colon prevents the user from having to escape the semicolon
- Xwhen referencing the filename.
- XThis option is useful only when multiple versions of the same file
- Xare on a single tape or when a file of the same name already
- Xexists in the destination directory.
- XThe default is to ignore version numbers.
- X.TP 8
- X.B d
- Xuse the directory structure from VMS, the default value is off.
- X.TP 8
- X.B e
- XProcess all filename extensions.
- XSince this program is mainly intended to move source code and possibly
- Xdata from a DEC system to a Unix system, the default is to ignore
- Xall files whose filename extension specifies system dependent data.
- XThe file types which will be ignored, unless the
- X.B e
- Xoption is specified, are
- X.IP "" 10
- Xexe VMS executable file
- X.br
- Xlib VMS object library file
- X.br
- Xobj RSX object file
- X.br
- Xodl RSX overlay description file
- X.br
- Xolb RSX object library file
- X.br
- Xpmd RSX post mortem dump file
- X.br
- Xstb RSX task symbol table file
- X.br
- Xsys RSX bootable system file
- X.br
- Xtsk RSX executable task file
- X.PP
- X.TP 8
- X.B f
- XUse the next argument in the command line as the tape device to
- Xbe used, rather than the default.
- X.sp
- XIf vmsbackup is compiled with the remote tape option
- Xand the file name has the form
- X.IR system [. user ]:/dev/???
- X.I vmsbackup
- Xwill use the tape drive /dev/??? on the remote system
- X.IR system ,
- Xvia
- X.IR rsh (1),
- Xand
- X.IR rmt (8).
- XThe optional
- X.I user
- Xportion of the pathname specifies the login name to use on the
- Xremote system.
- XIf it is not supplied, the current user's login name will be used.
- XIn all the cases, the user must have the appropriate
- Xpermissions on the remote machine, in order to use this facility.
- XThe default is
- X.I /dev/rmt8
- X(drive 0, raw mode, 1600 bpi).
- XThis must be a raw mode tape device.
- X.TP 8
- X.B s saveset
- XProcess only the given saveset number.
- X.TP 8
- X.B t
- XProduce a table of contents (a directory listing) on the standard output
- Xof the files on tape.
- X.TP 8
- X.B v
- XVerbose output.
- XNormally
- X.I vmsbackup
- Xdoes its work silently.
- XThe verbose option will cause the filenames of the files being read from
- Xtape to disk to be output on the standard output.
- X.TP 8
- X.B w
- X.I vmsbackup
- Xprints the action to be taken followed by file name, then
- Xwait for user confirmation. If a word beginning with `y'
- Xis given, the action is done. Any other input means don't do it.
- X.TP 8
- X.B x
- Xextract the named files from the tape.
- X.TP 8
- XThe optional
- X.I name
- Xargument specifies one or more filenames to be
- Xsearched for specifically on the tape and only those files are to be processed.
- XThe name may contain the usal sh(1) meta-characters *?![] \nnn.
- X.SH FILES
- X/dev/rmt\fIx\fP
- X.SH SEE ALSO
- Xrmtops(3)
- X.SH BUGS
- XThe filename match uses the complete VMS file names.
- X
- X.SH AUTHOR
- XJohn Douglas Carey
- X.br
- XSven-Ove Westberg
- SHAR_EOF
- if test 3444 -ne "`wc -c < 'vmsbackup.1'`"
- then
- echo shar: "error transmitting 'vmsbackup.1'" '(should have been 3444 characters)'
- fi
- fi
- echo shar: "extracting 'Makefile'" '(605 characters)'
- if test -f 'Makefile'
- then
- echo shar: "will not over-write existing file 'Makefile'"
- else
- sed 's/^ X//' << \SHAR_EOF > 'Makefile'
- X#
- X#
- XREMOTE=-DREMOTE # -DREMOTE use remote tape
- XSWAP= # -DSWAP swap bytes
- XCFLAGS= $(SWAP) $(REMOTE)
- XLFLAGS=
- XLIBS= -lrmt # remote magtape library
- XOWNER=tar # user for remote tape access
- XMODE=4755
- XBINDIR=/usr/local/bin
- XMANSEC=l
- XMANDIR=/usr/man/man$(MANSEC)
- X
- X#
- Xvmsbackup: vmsbackup.o getopt.o match.o
- X cc $(LFLAGS) -o vmsbackup vmsbackup.o match.o getopt.o $(LIBS)
- Xinstall:
- X install -m $(MODE) -o $(OWNER) -s vmsbackup $(BINDIR)
- X cp vmsbackup.1 $(MANDIR)/vmsbackup.$(MANSEC)
- Xclean:
- X rm -f vmsbackup *.o core
- Xshar:
- X shar -a README vmsbackup.1 Makefile vmsbackup.c match.c \
- X > vmsbackup.shar
- SHAR_EOF
- if test 605 -ne "`wc -c < 'Makefile'`"
- then
- echo shar: "error transmitting 'Makefile'" '(should have been 605 characters)'
- fi
- fi
- echo shar: "extracting 'vmsbackup.c'" '(16594 characters)'
- if test -f 'vmsbackup.c'
- then
- echo shar: "will not over-write existing file 'vmsbackup.c'"
- else
- sed 's/^ X//' << \SHAR_EOF > 'vmsbackup.c'
- X/*
- X *
- X * Title:
- X * Backup
- X *
- X * Decription:
- X * Program to read VMS backup tape
- X *
- X * Author:
- X * John Douglas CAREY.
- X * Sven-Ove Westberg (version 3.0)
- X *
- X * Net-addess:
- X * john%monu1.oz@seismo.ARPA
- X * luthcad!sow@enea.UUCP
- X *
- X * History:
- X * Version 1.0 - September 1984
- X * Can only read variable length records
- X * Version 1.1
- X * Cleaned up the program from the original hack
- X * Can now read stream files
- X * Version 1.2
- X * Now convert filename from VMS to UNIX
- X * and creates sub-directories
- X * Version 1.3
- X * Works on the Pyramid if SWAP is defined
- X * Version 1.4
- X * Reads files spanning multiple tape blocks
- X * Version 1.5
- X * Always reset reclen = 0 on file open
- X * Now output fixed length records
- X *
- X * Version 2.0 - July 1985
- X * VMS Version 4.0 causes a rethink !!
- X * Now use mtio operations instead of opening and closing file
- X * Blocksize now grabed from the label
- X *
- X * Version 2.1 - September 1985
- X * Handle variable length records of zero length.
- X *
- X * Version 2.2 - July 1986
- X * Handle FORTRAN records of zero length.
- X * Inserted exit(0) at end of program.
- X * Distributed program in aus.sources
- X *
- X * Version 2.3 - August 1986
- X * Handle FORTRAN records with record length fields
- X * at the end of a block
- X * Put debug output to a file.
- X * Distributed program in net.sources
- X *
- X * Version 3.0 - December 1986
- X * Handle multiple saveset
- X * Remote tape
- X * Interactive mode
- X * File name selection with meta-characters
- X * Convert ; to : in VMS filenames
- X * Flag for usage of VMS directory structure
- X * Flag for "useless" files eg. *.exe
- X * Flag for use VMS version in file names
- X * Flag for verbose mode
- X * Flag to list the contents of the tape
- X * Distributed to mod.sources
- X *
- X *
- X * Installation:
- X *
- X * Computer Centre
- X * Monash University
- X * Wellington Road
- X * Clayton
- X * Victoria 3168
- X * AUSTRALIA
- X *
- X */
- X#include <stdio.h>
- X#include <ctype.h>
- X
- X#include <sys/ioctl.h>
- X#include <sys/types.h>
- X#ifdef REMOTE
- X#include <local/rmt.h>
- X#include <sys/stat.h>
- X#endif
- X#include <sys/mtio.h>
- X#include <sys/file.h>
- X
- X#ifdef pyr
- X#define SWAP
- X#endif pyr
- X
- X#ifdef sun
- X#define SWAP
- X#endif
- X
- Xstruct bbh {
- X short bbh_dol_w_size;
- X short bbh_dol_w_opsys;
- X short bbh_dol_w_subsys;
- X short bbh_dol_w_applic;
- X long bbh_dol_l_number;
- X char bbh_dol_t_spare_1[20];
- X short bbh_dol_w_struclev;
- X short bbh_dol_w_volnum;
- X long bbh_dol_l_crc;
- X long bbh_dol_l_blocksize;
- X long bbh_dol_l_flags;
- X char bbh_dol_t_ssname[32];
- X short bbh_dol_w_fid[3];
- X short bbh_dol_w_did[3];
- X char bbh_dol_t_filename[128];
- X char bbh_dol_b_rtype;
- X char bbh_dol_b_rattrib;
- X short bbh_dol_w_rsize;
- X char bbh_dol_b_bktsize;
- X char bbh_dol_b_vfcsize;
- X short bbh_dol_w_maxrec;
- X long bbh_dol_l_filesize;
- X char bbh_dol_t_spare_2[22];
- X short bbh_dol_w_checksum;
- X} *block_header;
- X
- Xstruct brh {
- X short brh_dol_w_rsize;
- X short brh_dol_w_rtype;
- X long brh_dol_l_flags;
- X long brh_dol_l_address;
- X long brh_dol_l_spare;
- X} *record_header;
- X
- X/* define record types */
- X
- X#define brh_dol_k_null 0
- X#define brh_dol_k_summary 1
- X#define brh_dol_k_volume 2
- X#define brh_dol_k_file 3
- X#define brh_dol_k_vbn 4
- X#define brh_dol_k_physvol 5
- X#define brh_dol_k_lbn 6
- X#define brh_dol_k_fid 7
- X
- Xstruct bsa {
- X short bsa_dol_w_size;
- X short bsa_dol_w_type;
- X char bsa_dol_t_text[1];
- X} *data_item;
- X
- X#ifdef STREAM
- Xchar *def_tapefile = "/dev/rts8";
- X#else
- Xchar *def_tapefile = "/dev/rmt8";
- X#endif
- Xchar *tapefile;
- X
- Xchar filename[128];
- Xint filesize;
- X
- Xchar recfmt; /* record format */
- X
- X#define FAB_dol_C_UDF 0 /* undefined */
- X#define FAB_dol_C_FIX 1 /* fixed-length record */
- X#define FAB_dol_C_VAR 2 /* variable-length record */
- X#define FAB_dol_C_VFC 3 /* variable-length with fixed-length control record */
- X#define FAB_dol_C_STM 4 /* RMS-11 stream record (valid only for sequential org) */
- X#define FAB_dol_C_STMLF 5 /* stream record delimited by LF (sequential org only) */
- X#define FAB_dol_C_STMCR 6 /* stream record delimited by CR (sequential org only) */
- X#define FAB_dol_C_MAXRFM 6 /* maximum rfm supported */
- X
- Xchar recatt; /* record attributes */
- X
- X#define FAB_dol_V_FTN 0 /* FORTRAN carriage control character */
- X#define FAB_dol_V_CR 1 /* line feed - record -carriage return */
- X#define FAB_dol_V_PRN 2 /* print-file carriage control */
- X#define FAB_dol_V_BLK 3 /* records don't cross block boundaries */
- X
- X#define FANO 20
- X
- X#ifdef pyr
- Xstatic struct bsa *file_table[FANO];
- X#else
- Xstruct bsa *file_table[FANO];
- X#endif
- X
- XFILE *f = NULL;
- Xint file_count;
- Xshort reclen;
- Xshort fix;
- Xshort recsize;
- Xint vfcsize;
- X
- X#ifdef NEWD
- XFILE *lf;
- X#endif NEWD
- X
- Xint fd; /* tape file descriptor */
- Xint cflag, dflag, eflag, sflag, tflag, vflag, wflag, xflag;
- Xint setnr;
- Xchar **gargv;
- Xint goptind, gargc;
- X
- X#define LABEL_SIZE 80
- Xchar label[LABEL_SIZE];
- X
- Xchar *block;
- Xint blocksize;
- X
- Xstruct mtop op;
- X
- XFILE *
- Xopenfile(fn)
- Xchar *fn;
- X{
- X char ufn[256];
- X char ans[80];
- X char *p, *q, s, *ext;
- X int procf;
- X
- X procf = 1;
- X /* copy fn to ufn and convert to lower case */
- X p = fn;
- X q = ufn;
- X while (*p) {
- X if (isupper(*p))
- X *q = *p - 'A' + 'a';
- X else
- X *q = *p;
- X p++;
- X q++;
- X }
- X *q = '\0';
- X
- X /* convert the VMS to UNIX and make the directory path */
- X p = ufn;
- X q = ++p;
- X while (*q) {
- X if (*q == '.' || *q == ']') {
- X s = *q;
- X *q = '\0';
- X if(procf && dflag) mkdir(p, 0777);
- X *q = '/';
- X if (s == ']')
- X break;
- X }
- X *q++;
- X }
- X *q++;
- X if(!dflag) p=q;
- X /* strip off the version number */
- X while (*q && *q != ';') {
- X if( *q == '.') ext = q;
- X q++;
- X }
- X if (cflag) {
- X *q = ':';
- X }
- X else {
- X *q = '\0';
- X }
- X if(!eflag && procf) procf = typecmp(++ext);
- X if(procf && wflag) {
- X printf("extract %s [ny]",filename);
- X fflush(stdout);
- X gets(ans);
- X if(*ans != 'y') procf = NULL;
- X }
- X if(procf)
- X /* open the file for writing */
- X return(fopen(p, "w"));
- X else
- X return(NULL);
- X}
- X
- Xtypecmp(str) /* Compare the filename type in str with our list
- X of file type to be ignored. Return 0 if the
- X file is to be ignored, return 1 if the
- X file is not in our list and should not be ignored. */
- Xregister char *str;
- X{
- X static char *type[] = {
- X "exe", /* vms executable image */
- X "lib", /* vms object library */
- X "obj", /* rsx object file */
- X "odl", /* rsx overlay description file */
- X "olb", /* rsx object library */
- X "pmd", /* rsx post mortem dump */
- X "stb", /* rsx symbol table */
- X "sys", /* rsx bootable system image */
- X "tsk", /* rsx executable image */
- X "dir",
- X "upd",
- X "tlo",
- X "tlb",
- X "" /* null string terminates list */
- X };
- X register int i;
- X
- X i = -1;
- X while (*type[++i])
- X if (strncmp(str, type[i],3) == 0)
- X return(0); /* found a match, file to be ignored */
- X return(1); /* no match found */
- X}
- X
- Xprocess_file(buffer)
- Xchar *buffer;
- X{
- X int i, n;
- X char *p, *q;
- X short dsize, nblk, lnch;
- X
- X int c;
- X short *s;
- X
- X int procf;
- X
- X s = (short *) buffer;
- X
- X /* check the header word */
- X if (*s != 257) {
- X printf("Snark: invalid data header\n");
- X exit(1);
- X }
- X
- X c = 2;
- X for (i = 0; i < FANO; i++) {
- X file_table[i] = (struct bsa *) &buffer[c];
- X#ifndef SWAP
- X dsize = file_table[i]->bsa_dol_w_size;
- X#else
- X swap(&file_table[i]->bsa_dol_w_size, &dsize, sizeof(short));
- X#endif
- X c += dsize + 4;
- X }
- X
- X /* extract file name */
- X#ifndef SWAP
- X dsize = file_table[0]->bsa_dol_w_size;
- X#else
- X swap(&file_table[0]->bsa_dol_w_size, &dsize, sizeof(short));
- X#endif
- X p = file_table[0]->bsa_dol_t_text;
- X q = filename;
- X for (i = 0; i < dsize; i++)
- X *q++ = *p++;
- X *q = '\0';
- X
- X /* extract file's record attributes */
- X#ifndef SWAP
- X dsize = file_table[5]->bsa_dol_w_size;
- X#else
- X swap(&file_table[5]->bsa_dol_w_size, &dsize, sizeof(short));
- X#endif
- X p = file_table[5]->bsa_dol_t_text;
- X recfmt = p[0];
- X recatt = p[1];
- X#ifndef SWAP
- X bcopy(&p[2], &recsize, sizeof(short));
- X#else
- X swap(&p[2], &recsize, sizeof(short));
- X#endif
- X vfcsize = p[15];
- X if (vfcsize == 0)
- X vfcsize = 2;
- X#ifdef DEBUG
- X printf("recfmt = %d\n", recfmt);
- X printf("recatt = %d\n", recatt);
- X printf("reclen = %d\n", recsize);
- X printf("vfcsize = %d\n", vfcsize);
- X#endif
- X#ifndef SWAP
- X bcopy(&p[10], &nblk, sizeof(short));
- X bcopy(&p[12], &lnch, sizeof(short));
- X#else
- X swap(&p[10], &nblk, sizeof(short));
- X swap(&p[12], &lnch, sizeof(short));
- X#endif
- X filesize = (nblk-1)*512 + lnch;
- X#ifdef DEBUG
- X printf("nbk = %d, lnch = %d\n", nblk, lnch);
- X printf("filesize = 0x%x\n", filesize);
- X#endif
- X
- X /* open the file */
- X if (f != NULL) {
- X fclose(f);
- X file_count = 0;
- X reclen = 0;
- X }
- X procf = 0;
- X if (goptind < gargc)
- X for(i=goptind; i < gargc; i++) {
- X procf |= match(filename,gargv[i]);
- X }
- X else
- X procf = 1;
- X if (tflag && procf)
- X printf( " %-35s %8d \n",filename,filesize);
- X if (xflag && procf) {
- X /* open file */
- X f = openfile(filename);
- X if(f != NULL && vflag) printf("extracting %s\n", filename);
- X }
- X}
- X/*
- X *
- X * process a virtual block record (file record)
- X *
- X */
- Xprocess_vbn(buffer, rsize)
- Xchar *buffer;
- Xunsigned short rsize;
- X{
- X int c, i;
- X
- X if (f == NULL) {
- X return;
- X }
- X i = 0;
- X while (file_count+i < filesize && i < rsize) {
- X switch (recfmt) {
- X case FAB_dol_C_FIX:
- X if (reclen == 0) {
- X reclen = recsize;
- X }
- X fputc(buffer[i], f);
- X i++;
- X reclen--;
- X break;
- X
- X case FAB_dol_C_VAR:
- X case FAB_dol_C_VFC:
- X if (reclen == 0) {
- X reclen = *((short *) &buffer[i]);
- X#ifdef SWAP
- X swap(&reclen, &reclen, sizeof(short));
- X#endif
- X#ifdef NEWD
- X fprintf(lf, "---\n");
- X fprintf(lf, "reclen = %d\n", reclen);
- X fprintf(lf, "i = %d\n", i);
- X fprintf(lf, "rsize = %d\n", rsize);
- X#endif NEWD
- X fix = reclen;
- X i += 2;
- X if (recfmt == FAB_dol_C_VFC) {
- X i += vfcsize;
- X reclen -= vfcsize;
- X }
- X } else if (reclen == fix
- X && recatt == (1 << FAB_dol_V_FTN)) {
- X /****
- X if (buffer[i] == '0')
- X fputc('\n', f);
- X else if (buffer[i] == '1')
- X fputc('\f', f);
- X *** sow ***/
- X fputc(buffer[i],f); /** sow **/
- X i++;
- X reclen--;
- X } else {
- X fputc(buffer[i], f);
- X i++;
- X reclen--;
- X }
- X if (reclen == 0) {
- X fputc('\n', f);
- X if (i & 1)
- X i++;
- X }
- X break;
- X
- X case FAB_dol_C_STM:
- X case FAB_dol_C_STMLF:
- X if (reclen < 0) {
- X printf("SCREAM\n");
- X }
- X if (reclen == 0) {
- X reclen = 512;
- X }
- X c = buffer[i++];
- X reclen--;
- X if (c == '\n') {
- X reclen = 0;
- X }
- X fputc(c, f);
- X break;
- X
- X case FAB_dol_C_STMCR:
- X c = buffer[i++];
- X if (c == '\r')
- X fputc('\n', f);
- X else
- X fputc(c, f);
- X break;
- X
- X default:
- X fclose(f);
- X unlink(filename);
- X fprintf(stderr, "Invalid record format = %d\n", recfmt);
- X return;
- X }
- X }
- X file_count += i;
- X}
- X#ifdef SWAP
- X/*
- X *
- X * do swapping for Motorola type architectures
- X *
- X */
- Xswap(from, to, nbytes)
- Xchar *from, *to;
- Xint nbytes;
- X{
- X int i, j;
- X char temp[100];
- X
- X for (i = 0; i < nbytes; i++)
- X temp[i] = from[i];
- X for (i = 0, j = nbytes-1; i < nbytes; i++, j--)
- X to[i] = temp[j];
- X}
- X#endif
- X/*
- X *
- X * process a backup block
- X *
- X */
- Xprocess_block(block, blocksize)
- Xchar *block;
- Xint blocksize;
- X{
- X
- X unsigned short bhsize, rsize, rtype;
- X unsigned long bsize, i;
- X
- X i = 0;
- X
- X /* read the backup block header */
- X block_header = (struct bbh *) &block[i];
- X i += sizeof(struct bbh);
- X
- X bhsize = block_header->bbh_dol_w_size;
- X bsize = block_header->bbh_dol_l_blocksize;
- X#ifdef SWAP
- X swap(&bhsize, &bhsize, sizeof(short));
- X swap(&bsize, &bsize, sizeof(long));
- X#endif
- X
- X /* check the validity of the header block */
- X if (bhsize != sizeof(struct bbh)) {
- X fprintf(stderr, "Snark: Invalid header block size\n");
- X exit(1);
- X }
- X if (bsize != 0 && bsize != blocksize) {
- X fprintf(stderr, "Snark: Invalid block size\n");
- X exit(1);
- X }
- X#ifdef DEBUG
- X printf("new block: i = %d, bsize = %d\n", i, bsize);
- X#endif
- X
- X /* read the records */
- X while (i < bsize) {
- X /* read the backup record header */
- X record_header = (struct brh *) &block[i];
- X i += sizeof(struct brh);
- X
- X rtype = record_header->brh_dol_w_rtype;
- X rsize = record_header->brh_dol_w_rsize;
- X#ifdef SWAP
- X swap(&rtype, &rtype, sizeof(short));
- X swap(&rsize, &rsize, sizeof(short));
- X#endif
- X#ifdef DEBUG
- X printf("rtype = %d\n", rtype);
- X printf("rsize = %d\n", rsize);
- X printf("flags = 0x%x\n", record_header->brh_dol_l_flags);
- X printf("addr = 0x%x\n", record_header->brh_dol_l_address);
- X printf("i = %d\n", i);
- X#endif
- X
- X switch (rtype) {
- X
- X case brh_dol_k_null:
- X#ifdef DEBUG
- X printf("rtype = null\n");
- X#endif
- X break;
- X
- X case brh_dol_k_summary:
- X#ifdef DEBUG
- X printf("rtype = summary\n");
- X#endif
- X break;
- X
- X case brh_dol_k_file:
- X#ifdef DEBUG
- X printf("rtype = file\n");
- X#endif
- X process_file(&block[i]);
- X break;
- X
- X case brh_dol_k_vbn:
- X#ifdef DEBUG
- X printf("rtype = vbn\n");
- X#endif
- X process_vbn(&block[i], rsize);
- X break;
- X
- X case brh_dol_k_physvol:
- X#ifdef DEBUG
- X printf("rtype = physvol\n");
- X#endif
- X break;
- X
- X case brh_dol_k_lbn:
- X#ifdef DEBUG
- X printf("rtype = lbn\n");
- X#endif
- X break;
- X
- X case brh_dol_k_fid:
- X#ifdef DEBUG
- X printf("rtype = fid\n");
- X#endif
- X break;
- X
- X default:
- X fprintf(stderr, " Snark: invalid record type\n");
- X fprintf(stderr, " record type = %d\n", rtype);
- X exit(1);
- X }
- X#ifdef pyr
- X i = i + rsize;
- X#else
- X i += rsize;
- X#endif
- X }
- X}
- X
- Xrdhead()
- X{
- X int i, nfound;
- X char name[80];
- X nfound = 1;
- X /* read the tape label - 4 records of 80 bytes */
- X while ((i = read(fd, label, LABEL_SIZE)) != 0) {
- X if (i != LABEL_SIZE) {
- X fprintf(stderr, "Snark: bad label record\n");
- X exit(1);
- X }
- X if (strncmp(label, "VOL1",4) == 0) {
- X sscanf(label+4, "%14s", name);
- X if(vflag || tflag) printf("Volume: %s\n",name);
- X }
- X if (strncmp(label, "HDR1",4) == 0) {
- X sscanf(label+4, "%14s", name);
- X sscanf(label+31, "%4d", &setnr);
- X }
- X /* get the block size */
- X if (strncmp(label, "HDR2", 4) == 0) {
- X nfound = 0;
- X sscanf(label+5, "%5d", &blocksize);
- X#ifdef DEBUG
- X printf("blocksize = %d\n", blocksize);
- X#endif
- X }
- X }
- X if((vflag || tflag) && !nfound)
- X printf("Saveset name: %s number: %d\n",name,setnr);
- X /* get the block buffer */
- X block = (char *) malloc(blocksize);
- X if (block == (char *) 0) {
- X fprintf(stderr, "memory allocation for block failed\n");
- X exit(1);
- X }
- X return(nfound);
- X}
- X
- Xrdtail()
- X{
- X int i;
- X char name[80];
- X /* read the tape label - 4 records of 80 bytes */
- X while ((i = read(fd, label, LABEL_SIZE)) != 0) {
- X if (i != LABEL_SIZE) {
- X fprintf(stderr, "Snark: bad label record\n");
- X exit(1);
- X }
- X if (strncmp(label, "EOF1",4) == 0) {
- X sscanf(label+4, "%14s", name);
- X if(vflag || tflag)
- X printf("End of saveset: %s\n\n\n",name);
- X }
- X }
- X}
- X
- Xusage(progname)
- Xchar *progname;
- X{
- X fprintf(stderr,
- X "Usage: %s -{tx}[cdevw][-s setnumber][-f tapefile]\n",progname);
- X}
- Xmain(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X
- X char *progname;
- X int c, i, eoffl;
- X int selset;
- X extern int optind;
- X extern char *optarg;
- X
- X progname = argv[0];
- X if(argc < 2){
- X usage(progname);
- X exit(1);
- X }
- X gargv = argv;
- X gargc = argc;
- X tapefile = def_tapefile;
- X cflag=dflag=eflag=sflag=tflag=vflag=wflag=xflag=0;
- X while((c=getopt(argc,argv,"cdef:s:tvwx")) != EOF)
- X switch(c){
- X case 'c':
- X cflag++;
- X break;
- X case 'd':
- X dflag++;
- X break;
- X case 'e':
- X eflag++;
- X break;
- X case 'f':
- X tapefile = optarg;
- X break;
- X case 's':
- X sflag++;
- X sscanf(optarg,"%d",&selset);
- X break;
- X case 't':
- X tflag++;
- X break;
- X case 'v':
- X vflag++;
- X break;
- X case 'w':
- X wflag++;
- X break;
- X case 'x':
- X xflag++;
- X break;
- X case '?':
- X usage(progname);
- X exit(1);
- X break;
- X };
- X if(!tflag && !xflag) {
- X usage(progname);
- X exit(1);
- X }
- X goptind = optind;
- X
- X#ifdef NEWD
- X /* open debug file */
- X lf = fopen("log", "w");
- X if (lf == NULL) {
- X perror("log");
- X exit(1);
- X }
- X#endif
- X
- X /* open the tape file */
- X fd = open(tapefile, O_RDONLY);
- X if (fd < 0) {
- X perror(tapefile);
- X exit(1);
- X }
- X
- X /* rewind the tape */
- X op.mt_op = MTREW;
- X op.mt_count = 1;
- X i = ioctl(fd, MTIOCTOP, &op);
- X if (i < 0) {
- X perror(tapefile);
- X exit(1);
- X }
- X
- X eoffl = rdhead();
- X /* read the backup tape blocks until end of tape */
- X while (!eoffl) {
- X if(sflag && setnr != selset) {
- X op.mt_op = MTFSF;
- X op.mt_count = 1;
- X i = ioctl(fd, MTIOCTOP, &op);
- X if (i < 0) {
- X perror(tapefile);
- X exit(1);
- X }
- X i = 0;
- X }
- X else
- X i = read(fd, block, blocksize);
- X if(i == 0) {
- X rdtail();
- X eoffl=rdhead();
- X }
- X else if (i != blocksize) {
- X fprintf(stderr, "bad block read i = %d\n", i);
- X exit(1);
- X }
- X else{
- X eoffl = 0;
- X process_block(block, blocksize);
- X }
- X }
- X if(vflag || tflag) printf("End of tape\n");
- X
- X /* close the tape */
- X close(fd);
- X
- X#ifdef NEWD
- X /* close debug file */
- X fclose(lf);
- X#endif NEWD
- X
- X /* exit cleanly */
- X exit(0);
- X}
- SHAR_EOF
- if test 16594 -ne "`wc -c < 'vmsbackup.c'`"
- then
- echo shar: "error transmitting 'vmsbackup.c'" '(should have been 16594 characters)'
- fi
- fi
- echo shar: "extracting 'match.c'" '(6723 characters)'
- if test -f 'match.c'
- then
- echo shar: "will not over-write existing file 'match.c'"
- else
- sed 's/^ X//' << \SHAR_EOF > 'match.c'
- X#include <stdio.h>
- X#include <sys/types.h>
- X
- X#define ASTERISK '*' /* The '*' metacharacter */
- X#define QUESTION '?' /* The '?' metacharacter */
- X#define LEFT_BRACKET '[' /* The '[' metacharacter */
- X#define RIGHT_BRACKET ']' /* The ']' metacharacter */
- X
- X#define IS_OCTAL(ch) (ch >= '0' && ch <= '7')
- X
- Xtypedef int BOOLEAN;
- X#define VOID void
- X#define TRUE 1
- X#define FALSE 0
- X#define EOS '\000'
- X
- Xstatic BOOLEAN do_list ();
- Xstatic char nextch ();
- Xstatic VOID list_parse ();
- X
- X
- X/*
- X * FUNCTION
- X *
- X * match test string for wildcard match
- X *
- X * SYNOPSIS
- X *
- X * BOOLEAN match (string, pattern)
- X * register char *string;
- X * register char *pattern;
- X *
- X * DESCRIPTION
- X *
- X * Test string for match using pattern. The pattern may
- X * contain the normal shell metacharacters for pattern
- X * matching. The '*' character matches any string,
- X * including the null string. The '?' character matches
- X * any single character. A list of characters enclosed
- X * in '[' and ']' matches any character in the list.
- X * If the first character following the beginning '['
- X * is a '!' then any character not in the list is matched.
- X *
- X */
- X
- X
- X/*
- X * PSEUDO CODE
- X *
- X * Begin match
- X * Switch on type of pattern character
- X * Case ASTERISK:
- X * Attempt to match asterisk
- X * Break
- X * Case QUESTION MARK:
- X * Attempt to match question mark
- X * Break
- X * Case EOS:
- X * Match is result of EOS on string test
- X * Break
- X * Case default:
- X * If explicit match then
- X * Match is result of submatch
- X * Else
- X * Match is FALSE
- X * End if
- X * Break
- X * End switch
- X * Return result of match test
- X * End match
- X *
- X */
- X
- XBOOLEAN match (string, pattern)
- Xregister char *string;
- Xregister char *pattern;
- X{
- X register BOOLEAN ismatch;
- X
- X ismatch = FALSE;
- X switch (*pattern) {
- X case ASTERISK:
- X pattern++;
- X do {
- X ismatch = match (string, pattern);
- X } while (!ismatch && *string++ != EOS);
- X break;
- X case QUESTION:
- X if (*string != EOS) {
- X ismatch = match (++string, ++pattern);
- X }
- X break;
- X case EOS:
- X if (*string == EOS) {
- X ismatch = TRUE;
- X }
- X break;
- X case LEFT_BRACKET:
- X if (*string != EOS) {
- X ismatch = do_list (string, pattern);
- X }
- X break;
- X default:
- X if (*string++ == *pattern++) {
- X ismatch = match (string, pattern);
- X } else {
- X ismatch = FALSE;
- X }
- X break;
- X }
- X return (ismatch);
- X}
- X
- X
- X/*
- X * FUNCTION
- X *
- X * do_list process a list and following substring
- X *
- X * SYNOPSIS
- X *
- X * static BOOLEAN do_list (string, pattern)
- X * register char *string;
- X * register char *pattern;
- X *
- X * DESCRIPTION
- X *
- X * Called when a list is found in the pattern. Returns
- X * TRUE if the current character matches the list and
- X * the remaining substring matches the remaining pattern.
- X *
- X * Returns FALSE if either the current character fails to
- X * match the list or the list matches but the remaining
- X * substring and subpattern's don't.
- X *
- X * RESTRICTIONS
- X *
- X * The mechanism used to match characters in an inclusive
- X * pair (I.E. [a-d]) may not be portable to machines
- X * in which the native character set is not ASCII.
- X *
- X * The rules implemented here are:
- X *
- X * (1) The backslash character may be
- X * used to quote any special character.
- X * I.E. "\]" and "\-" anywhere in list,
- X * or "\!" at start of list.
- X *
- X * (2) The sequence \nnn becomes the character
- X * given by nnn (in octal).
- X *
- X * (3) Any non-escaped ']' marks the end of list.
- X *
- X * (4) A list beginning with the special character
- X * '!' matches any character NOT in list.
- X * The '!' character is only special if it
- X * is the first character in the list.
- X *
- X */
- X
- X
- X/*
- X * PSEUDO CODE
- X *
- X * Begin do_list
- X * Default result is no match
- X * Skip over the opening left bracket
- X * If the next pattern character is a '!' then
- X * List match gives FALSE
- X * Skip over the '!' character
- X * Else
- X * List match gives TRUE
- X * End if
- X * While not at closing bracket or EOS
- X * Get lower and upper bounds
- X * If character in bounds then
- X * Result is same as sense flag.
- X * Skip over rest of list
- X * End if
- X * End while
- X * If match found then
- X * If not at end of pattern then
- X * Call match with rest of pattern
- X * End if
- X * End if
- X * Return match result
- X * End do_list
- X *
- X */
- X
- Xstatic BOOLEAN do_list (string, pattern)
- Xregister char *string;
- Xchar *pattern;
- X{
- X register BOOLEAN ismatch;
- X register BOOLEAN if_found;
- X register BOOLEAN if_not_found;
- X auto char lower;
- X auto char upper;
- X
- X pattern++;
- X if (*pattern == '!') {
- X if_found = FALSE;
- X if_not_found = TRUE;
- X pattern++;
- X } else {
- X if_found = TRUE;
- X if_not_found = FALSE;
- X }
- X ismatch = if_not_found;
- X while (*pattern != ']' && *pattern != EOS) {
- X list_parse (&pattern, &lower, &upper);
- X if (*string >= lower && *string <= upper) {
- X ismatch = if_found;
- X while (*pattern != ']' && *pattern != EOS) {pattern++;}
- X }
- X }
- X if (*pattern++ != ']') {
- X fprintf (stderr, "warning - character class error\n");
- X } else {
- X if (ismatch) {
- X ismatch = match (++string, pattern);
- X }
- X }
- X return (ismatch);
- X}
- X
- X
- X/*
- X * FUNCTION
- X *
- X * list_parse parse part of list into lower and upper bounds
- X *
- X * SYNOPSIS
- X *
- X * static VOID list_parse (patp, lowp, highp)
- X * char **patp;
- X * char *lowp;
- X * char *highp;
- X *
- X * DESCRIPTION
- X *
- X * Given pointer to a pattern pointer (patp), pointer to
- X * a place to store lower bound (lowp), and pointer to a
- X * place to store upper bound (highp), parses part of
- X * the list, updating the pattern pointer in the process.
- X *
- X * For list characters which are not part of a range,
- X * the lower and upper bounds are set to that character.
- X *
- X */
- X
- Xstatic VOID list_parse (patp, lowp, highp)
- Xchar **patp;
- Xchar *lowp;
- Xchar *highp;
- X{
- X *lowp = nextch (patp);
- X if (**patp == '-') {
- X (*patp)++;
- X *highp = nextch (patp);
- X } else {
- X *highp = *lowp;
- X }
- X}
- X
- X
- X/*
- X * FUNCTION
- X *
- X * nextch determine next character in a pattern
- X *
- X * SYNOPSIS
- X *
- X * static char nextch (patp)
- X * char **patp;
- X *
- X * DESCRIPTION
- X *
- X * Given pointer to a pointer to a pattern, uses the pattern
- X * pointer to determine the next character in the pattern,
- X * subject to translation of backslash-char and backslash-octal
- X * sequences.
- X *
- X * The character pointer is updated to point at the next pattern
- X * character to be processed.
- X *
- X */
- X
- Xstatic char nextch (patp)
- Xchar **patp;
- X{
- X register char ch;
- X register char chsum;
- X register int count;
- X
- X ch = *(*patp)++;
- X if (ch == '\\') {
- X ch = *(*patp)++;
- X if (IS_OCTAL (ch)) {
- X chsum = 0;
- X for (count = 0; count < 3 && IS_OCTAL (ch); count++) {
- X chsum *= 8;
- X chsum += ch - '0';
- X ch = *(*patp)++;
- X }
- X (*patp)--;
- X ch = chsum;
- X }
- X }
- X return (ch);
- X}
- SHAR_EOF
- if test 6723 -ne "`wc -c < 'match.c'`"
- then
- echo shar: "error transmitting 'match.c'" '(should have been 6723 characters)'
- fi
- fi
- exit 0
- # End of shell archive
-
-